const _ = require('lodash');
const async = require('async');
const passport = require('passport');
const { PassportConfigurator } = require('loopback-component-passport');
const SG = require('strong-globalize');
const crypto = require('crypto');
const assert = require('assert');
const services = require('../../../services');

const commonService = services.common;

const g = SG();

module.exports = function config(app) {
  app.enableAuth();

  passport.serializeUser((user, done) => {
    const { SysUserRoleMapping: userRoleMappingModel, SysRole: userRole } = commonService.getModels();
    //if (process.env.NODE_ENV == 'development') return done(null, user);
    let isExist = true;
    const getUserRoleMappingCount = (next) => {
      commonService.getCount(userRoleMappingModel, { userEmployeeId: user.employeeId },
        (error, count) => {
          isExist = count !== 0;
          next(error,count);
        });
    };
    const getDefaultRoleList = (count, next) => {
      if (isExist) return next(null, []);
      commonService.getList(userRole, { where: { isDefault: true } }, next);
    };
    const createUserRoleMappingList = (defaultRoleList, next) => {
      if (isExist) return next(null, []);
      const userRoleMappingList = [];
      _.forEach(defaultRoleList, defaultRoleItem => userRoleMappingList.push({ userEmployeeId: user.employeeId, roleId: defaultRoleItem.id }));
      userRoleMappingModel.create(userRoleMappingList, next);
    };
    async.waterfall([getUserRoleMappingCount, getDefaultRoleList, createUserRoleMappingList],
      error =>
      done(error, user));
  });

  passport.deserializeUser((user, done) => {
    done(null, user);
  });

  const passportConfigurator = new PassportConfigurator(app);
  passportConfigurator.init();
  passportConfigurator.setupModels({
    userModel: app.models.SysUser,
    userIdentityModel: app.models.SysUserIdentity,
    userCredentialModel: app.models.UserCredential,
  });

  return function (providers) {
    _.forEach(providers, (provider, key) => {
      provider.profileToUser = profileToUser;
      provider.session = provider.session !== false;
      passportConfigurator.configureProvider(key, provider);
    });
  };
};

function profileToUser(provider, profile, options) { // eslint-disable-line
  // if (process.env.NODE_ENV == 'development') {
  //   if (profile.id == 'C252663') return {employeeId: 'C252663', chineseName: '孙洋', englishName: 'Adis Sun', email: 'adis.sun@innocellence.com', password: '123456' };
  //   if (profile.id == 'C217353') return {employeeId: 'C217353', chineseName: '何英', englishName: 'Ying He', email: 'ying.he@innocellence.com', password: '123456' };
  // }
  const profileEmail = profile.emails && profile.emails[0] && profile.emails[0].value;
  const generatedEmail = `${profile.username || profile.id}@loopback.${
    profile.provider || provider}.com`;
  const email = profile.skipEmail ? profileEmail : (profileEmail || generatedEmail);
  const username = `${provider}.${profile.username || profile.id}`;
  const password = generateKey('password');
  const userObj = {
    username,
    password,
    employeeId: profile.id,
    chineseName: profile.chineseName ? profile.chineseName : `${profile.id}`,
    englishName: `${profile.id}`,
  };
  if (email) {
    userObj.email = email;
  }
  return userObj;
}

function generateKey(hmacKey, algorithm, encoding) {
  assert(hmacKey, g.f('{{HMAC}} key is required'));
  algorithm = algorithm || 'sha1';
  encoding = encoding || 'hex';
  const hmac = crypto.createHmac(algorithm, hmacKey);
  const buf = crypto.randomBytes(32);
  hmac.update(buf);
  const key = hmac.digest(encoding);
  return key;
}
